package cn.congine.wizarpos.mall.service.impl;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Service;

import cn.congine.wizarpos.mall.exception.MangoException;
import cn.congine.wizarpos.mall.utils.SysConstants;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

@Service("wposHttpClient")
public class WPosHttpClient {
	private final Log log = LogFactory.getLog(getClass());
	private static final int DEFAULT_TIMEOUT = 10000;
	private static final String WPCharset = "UTF-8";
	private static final String JsonContentType = "application/json";
//	private CloseableHttpClient httpClient;
	private static String memberURL = "";
	private static String cashierURL = "";
	private static String openURL = "";
	@Resource(name = "messageSource")
	private MessageSource messageSource;

	@PostConstruct
	public void initialize() {
		memberURL = messageSource.getMessage(SysConstants.POS_SERVICE_MEMBER,
				null, Locale.ENGLISH);
		cashierURL = messageSource.getMessage(SysConstants.POS_SERVICE_CASHIER,
				null, Locale.ENGLISH);
		openURL = messageSource.getMessage(SysConstants.POS_SERVICE_OPEN, null,
				Locale.ENGLISH);
		log.debug("memberURL = " + memberURL);
		log.debug("cashierURL = " + cashierURL);
		log.debug("openURL = " + openURL);
	}

	/**
	 * web service 请求得到交易流水号
	 * 
	 * @param mid
	 * @return
	 * @throws MangoException
	 */
	public String getTranLogId(String mid) throws Exception {
		JSONObject param = new JSONObject();
		param.put("mid", mid);
		;
		JSONObject json = new JSONObject();
		json.put("service_code", "1010");
		json.put("param", param);
		return (String) postMember(json).getJSONObject("result").get(
				"tranLogId");
	}

	/**
	 * web service 请求得到微信交易订单流水号
	 * 
	 * @param mid
	 * @return
	 * @throws MangoException
	 */
	public String getOrderId(String mid) throws Exception {
		JSONObject param = new JSONObject();
		param.put("mid", mid);
		;
		JSONObject json = new JSONObject();
		json.put("service_code", "1012");
		json.put("param", param);
		return (String) postMember(json).getJSONObject("result").get(
				"wxOrderId");
	}

	/**
	 * 取会员券流水号,T打头
	 * 
	 * @param mid
	 * @return
	 */
	public String getTicketInfoNO(String mid) {
		JSONObject param = new JSONObject();
		param.put("mid", mid);// mid慧商户号
		JSONObject json = new JSONObject();
		json.put("service_code", "1011");
		json.put("param", param);
		String ticketInfoId = null;
		try {
			JSONObject resJson = postMember(json);
			ticketInfoId = resJson.getJSONObject("result").getString(
					"ticketInfoId");
		} catch (Exception e) {
			throw new RuntimeException("生成序列号错误");
		}
		if (ticketInfoId == null) {
			throw new RuntimeException("生成序列号错误");
		}
		return ticketInfoId;
	}

	// 请求会员易 pos service
	public JSONObject postMember(JSONObject json) throws Exception {
		return post(memberURL, json);
	}

	// 请求收银易 pos service
	public JSONObject postCashier(JSONObject json) throws Exception {
		return post(cashierURL, json);
	}

	// 请求开放平台接口
	public JSONObject postOpen(String method, JSONObject json) throws Exception {
		return post(openURL + method, json);
	}

	public JSONObject post(String url, JSONObject json) throws Exception {
		System.out.print("-------WPosHttpClient.post()-------url = " + url);
		RequestConfig requestConfig = RequestConfig.custom()
				.setSocketTimeout(DEFAULT_TIMEOUT)
				.setConnectTimeout(DEFAULT_TIMEOUT)
				.setCookieSpec(CookieSpecs.BROWSER_COMPATIBILITY).build();
		
		CloseableHttpClient  httpClient = HttpClients.custom()
				.setDefaultRequestConfig(requestConfig).build();

		HttpPost httpPost = new HttpPost(url);
		// TODO 请求报文需要签名
		/* json.put("signature", ""); */

		log.debug("request json:" + json.toJSONString());
		CloseableHttpResponse response = null;
		try {
			StringEntity postEntity = new StringEntity(json.toJSONString(),
					ContentType.create(JsonContentType, WPCharset));
			httpPost.setEntity(postEntity);
			for (int i = 0; i < 3; i++) {
				response = httpClient.execute(httpPost);
				if (response.getStatusLine().getStatusCode() == HttpURLConnection.HTTP_OK) {
					break;
				}
			}
			log.debug("StatusCode:" + response.getStatusLine().getStatusCode());
			if (response.getStatusLine().getStatusCode() != HttpURLConnection.HTTP_OK) {
				System.out.print(response.getEntity().getContent());
				throw new Exception("Access failed");
			}
			byte[] result = EntityUtils.toByteArray(response.getEntity());
			return parseResult(result);
		} catch (UnknownHostException he) {
			
			response = httpClient.execute(httpPost);
			
			log.debug("StatusCode:" + response.getStatusLine().getStatusCode());
			if (response.getStatusLine().getStatusCode() != HttpURLConnection.HTTP_OK) {
				throw new Exception("Access failed");
			}
			byte[] result = EntityUtils.toByteArray(response.getEntity());
			return parseResult(result);
		} catch (Exception e) {
			log.error("调用服务器失败!" + e);
			throw new Exception("调用服务器失败!");
		} finally {
			if (response != null) {
				try {
					response.close();
				} catch (IOException e) {
					log.error(e);
				}
			}
		}
	}

	public JSONObject get(String url) throws Exception {
		System.out.print("-------WPosHttpClient.get()-------url = " + url);
		RequestConfig requestConfig = RequestConfig.custom()
				.setSocketTimeout(DEFAULT_TIMEOUT)
				.setConnectTimeout(DEFAULT_TIMEOUT)
				.setCookieSpec(CookieSpecs.BROWSER_COMPATIBILITY).build();
		
		CloseableHttpClient  httpClient = HttpClients.custom()
				.setDefaultRequestConfig(requestConfig).build();
		
		HttpGet httpGet = new HttpGet(url);

		HttpResponse response = null;
		try {
			for (int i = 0; i < 3; i++) { //考虑网络问题，最多请求3此
				response = httpClient.execute(httpGet);
				if (response.getStatusLine().getStatusCode() == HttpURLConnection.HTTP_OK) {
					break;
				}
			}
			log.debug("StatusCode:" + response.getStatusLine().getStatusCode());
			if (response.getStatusLine().getStatusCode() != HttpURLConnection.HTTP_OK) {
				System.out.print(response.getEntity().getContent());
				throw new Exception("Access failed");
			}
			byte[] result = EntityUtils.toByteArray(response.getEntity());
			return parseResult(result);
		} catch (Exception e) {
			log.error("微信接口服务器失败!" + e);
			throw new Exception("Access failed");
		}
	}

	private JSONObject parseResult(byte[] response) throws Exception {
		JSONObject json = null;
		if ((response == null) || (response.length == 0)) {
			throw new Exception("无响应报文");
		}
		String content = toString(response, WPCharset);
		log.debug("response json:" + content);
		json = JSONObject.parseObject(content);
		// TODO 响应报文需要验证签名
		return json;
	}

	private String toString(byte[] content, String charsetName)
			throws Exception {
		try {
			return new String(content, charsetName);
		} catch (UnsupportedEncodingException e) {
			throw new Exception("Unsupported encoding");
		}
	}

	/**
	 * 取预约单流水号
	 * 
	 * @param mid
	 * @return
	 */
	public String getCarterOrderNo(String mid) {
		JSONObject param = new JSONObject();
		param.put("mid", mid);// mid慧商户号
		JSONObject json = new JSONObject();
		json.put("service_code", "1002");
		json.put("param", param);
		String carterOrderNo = null;
		try {
			JSONObject resJson = postCashier(json);
			carterOrderNo = resJson.getJSONObject("result").getString(
					"carterOrderNo");
		} catch (Exception e) {
			throw new RuntimeException("取预约单流水号错误");
		}
		if (carterOrderNo == null) {
			throw new RuntimeException("取预约单流水号错误");
		}

		return carterOrderNo;
	}

	/**
	 * 查询微信会员卡是否存在
	 * 
	 * @param mid
	 * @return
	 */
	public JSONObject getMerchantCardByOpenId(String openId, String mid) {
		JSONObject param = new JSONObject();
		param.put("mid", mid);// mid慧商户号
		param.put("openId", openId);// mid慧商户号
		JSONObject json = new JSONObject();
		json.put("service_code", "1002");
		json.put("param", param);

		JSONObject resJson = new JSONObject();
		try {
			// 调用会员易对外接口查询是否存在微信会员卡
			resJson = postMember(json);
		} catch (Exception e) {
			throw new RuntimeException("查询微信会员卡是否存在出错");
		}

		return resJson;
	}
	

	/**
	 * 查询会员卡券信息
	 * 
	 * @param mid
	 * @return
	 */
	public JSONObject getMemberTicketInfo(String openId, String mid) {
		JSONObject param = new JSONObject();
		param.put("mid", mid);// mid慧商户号
		param.put("openId", openId);// 
		JSONObject json = new JSONObject();
		json.put("service_code", "1003");
		json.put("param", param);

		JSONObject resJson = new JSONObject();
		try {
			resJson = postMember(json);
		} catch (Exception e) {
			throw new RuntimeException("查询会员卡券信息出错");
		}

		return resJson;
	}
	
	/**
	 * 获取会员卡临牌
	 * 
	 * @param mid
	 * @return
	 */
	public JSONObject getQRcodeTokenId(String openId, String mid) {
		JSONObject param = new JSONObject();
		param.put("mid", mid);// mid慧商户号
		param.put("openId", openId);// 
		JSONObject json = new JSONObject();
		json.put("service_code", "1005");
		json.put("param", param);

		JSONObject resJson = new JSONObject();
		try {
			resJson = postMember(json);
		} catch (Exception e) {
			throw new RuntimeException("查询会员卡券信息出错");
		}

		return resJson;
	}

	/**
	 * 快速注册微信会员卡
	 * 
	 * @param mid
	 * @return
	 */
	public JSONObject registerVipCard(String openId, String mid, String name, String phone) {
		JSONObject param = new JSONObject();
		param.put("mid", mid);// mid慧商户号
		param.put("openId", openId);// mid慧商户号
		param.put("name", name);
		param.put("phone", phone);

		JSONObject json = new JSONObject();
		json.put("service_code", "1001");
		json.put("param", param);

		JSONObject resJson = new JSONObject();
		try {
			// 调用会员易对外接口查询是否存在微信会员卡
			resJson = postMember(json);

		} catch (Exception e) {
			throw new RuntimeException("注册会员卡失败!");
		}

		return resJson;
	}

	/**
	 * 实体会员卡绑定微信会员卡
	 * 
	 * @param mid
	 *            慧商户号
	 * @param cardNo
	 *            实体会员卡号
	 * @param bindNo
	 *            微信会员卡号
	 * @return
	 * @throws Exception
	 */
	public void bindMemberCard(String mid, String cardNo, String bindNo)
			throws Exception {// 1020 实体会员卡绑定微信会员卡
		JSONObject param = new JSONObject();
		param.put("mid", mid);// 慧商户号
		param.put("cardNo", cardNo);// 实体会员卡号
		param.put("bindNo", bindNo);// 微信会员卡号

		JSONObject json = new JSONObject();
		json.put("param", param);
		json.put("service_code", "1020");

		postMember(json);
	}
	
	/**
	 * 会员消费 1034,按规则赠送积分、券
	 * 
	 * @param mid
	 * @param cardNo
	 * @param amount
	 * @throws Exception
	 */
	public JSONObject transactByRule(String mid, String openId, String cardNo, int payAmount, String wxOrderId, String payType)
			throws Exception { 
		JSONObject param = new JSONObject();
		param.put("mid", mid); // 慧商户号
		param.put("openId", openId); // openId
		param.put("wxOrderId", wxOrderId); // 微信订单ID
		param.put("cardNo", cardNo); // 会员卡号
		param.put("payAmount", payAmount); // 交易金额(整型 分为单位)
		param.put("payType", payType); // 1 货到付款 2 微信支付送货上门 3 微信支付到店提货 4 会员卡支付送货上门 5 会员卡支付到店提货
		
		JSONObject json = new JSONObject();
		json.put("param", param);
		json.put("service_code", "1034");

		JSONObject resJson = null;
		try {
			resJson = postMember(json);
		} catch (Exception e) {
			log.error(e.getMessage());
			return null;
		}
		
		return resJson;
	}
	
	/**
	 * 收款前接口1033,获取会员折扣价
	 * 
	 * @param mid
	 * @param cardNo
	 * @param productId
	 * @throws Exception
	 */
	public Map<String, Integer> priceByRule(String mid, String cardNo, String productId) {
		JSONObject param = new JSONObject();
		param.put("mid", mid); // 慧商户号
		param.put("cardNo", cardNo); // 会员卡号
		param.put("productId", productId); // 商品id，多个商品用","分开拼成一个字符串
		
		JSONObject json = new JSONObject();
		json.put("param", param);
		json.put("service_code", "1033");
		
		JSONObject resJson = null;
		try {
			resJson = postMember(json);
		} catch (Exception e) {
			log.error(e.getMessage());
			return null;
		}
		
		Map<String, Integer> priceMap = new HashMap<String, Integer>(); 
		if (resJson == null || !resJson.containsKey("code") || !"0".equals(resJson.get("code"))) {
			return null;
		}
		
		JSONArray memberPrice = resJson.getJSONObject("result").getJSONArray("memberPrice");
		if (memberPrice == null || memberPrice.isEmpty()) {
			return null;
		}
		
		for (int i = 0; i < memberPrice.size(); i++) {
			String str = memberPrice.get(i).toString();
			if (!str.contains("|")) {
				continue;
			}
			String[] arr = str.split("|");
			priceMap.put(arr[0], Integer.parseInt(arr[1]));
		}
		
		return priceMap;
	}
	
	/**
	 * 获取可用的餐桌列表
	 * 
	 * @param mid
	 * 			慧商户号
	 * @param date
	 * 			日期
	 * @param timeId
	 * 			时段Id
	 * @return
	 */
	public JSONArray getUnUsedErpTable(String mid, String date, String timeId) {
		JSONObject param = new JSONObject();
		param.put("mid", mid); // 慧商户号
		param.put("date", date); // 日期
		param.put("timeId", timeId); // 时段Id
		
		JSONObject response = null;
		try {
			response = postOpen("/catering/table/unused", param);
		} catch (Exception e) {
			log.error(e.getMessage());
			return null;
		}
		
		if (!response.containsKey("code") || !"0".equals(response.get("code"))) {
			log.error(response.get("message"));
			return null;
		}
		
		JSONArray result = response.getJSONArray("result");
		if (result == null || result.isEmpty()) {
			return null;
		}
		
		return result;
	}
	
	public boolean isTableUsing(String mid, String tableId) {
		JSONObject param = new JSONObject();
		param.put("mid", mid); // 慧商户号
		param.put("tableId", tableId); // 时段Id
		
		JSONObject response = null;
		try {
			response = postOpen("/catering/table/using", param);
		} catch (Exception e) {
			log.error(e.getMessage());
			return false;
		}
		
		if (!response.containsKey("code") || !"0".equals(response.get("code"))) {
			log.error(response.get("message"));
			return false;
		}
		
		JSONObject result = response.getJSONObject("result");
		if (result == null || result.isEmpty()) {
			return false;
		}
		
		return result.getBoolean("using");
	}
	
	/**
	 * 获取用户可用商户代金券
	 * 
	 * @param mid
	 * @return
	 */
	public JSONObject getCashTickets(String openId, String mid) {
		JSONObject param = new JSONObject();
		param.put("mid", mid);// mid慧商户号
		param.put("openId", openId);// mid慧商户号
		JSONObject json = new JSONObject();
		json.put("service_code", "1039");
		json.put("param", param);

		JSONObject resJson = new JSONObject();
		try {
			// 调用会员易对外接口查询是否存在微信会员卡
			resJson = postMember(json);
		} catch (Exception e) {
			throw new RuntimeException("获取用户可用商户代金券请求出错");
		}

		return resJson;
	}
	
	/**
	 * 获取第三方会员折扣
	 * 
	 * @param mid
	 * @return
	 */
	public JSONObject getThirdDiscount(String openId, String mid) {
		// TODO
		return null;
	}
	
	/**
	 * 取自定义微信券号,W打头
	 * 
	 * @param mid
	 * @return
	 */
	public String getTicketCode(String mid) {
		JSONObject param = new JSONObject();
		param.put("mid", mid);// mid慧商户号
		JSONObject json = new JSONObject();
		json.put("service_code", "1017");
		json.put("param", param);
		JSONObject resJson = null;
		
		try {
			resJson = postMember(json);
		} catch (Exception e) {
			throw new RuntimeException("生成券号出错");
		}
		
		String ticketInfoId = null;
		if (resJson != null && resJson.containsKey("code") 
				&& 0==resJson.getIntValue("code")) {
			ticketInfoId = resJson.getJSONObject("result")
					.getString("ticketInfoId");
		}
		
		if (ticketInfoId == null) {
			throw new RuntimeException("生成自定义微信券号出错");
		}
	
		return ticketInfoId;
	}
}
